﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using Xenta.Structs;
using Xenta.Utils;
using Xenta.Attributes;
using Xenta.Web.Controllers;

namespace Xenta.Web.Areas.FileSystem.Controllers
{
    [Authenticate, InRole("ADMIN")]
    public sealed class FileController : ExtController
    {
        #region GET/POST Actions

        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public ActionResult GoTo(int? id, string guid)
        {
            if(!id.HasValue)
            {
                dynamic m = null;
                if(!String.IsNullOrWhiteSpace(guid))
                {
                    m = Svc.ProcessOperation("GetFileByGuid", new
                    {
                        Guid = guid.ParseAs<Guid>()
                    });
                }
                if(m == null)
                    return HttpNotFound();
                id = JDM.Int32(m.EntityID);
            }
            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id
            }));
        }

        [HttpGet, RestoreState]
        public ActionResult Create()
        {
            return View();
        }

        [HttpPost, PersistState]
        public ActionResult Create(int ownerID, 
            int folderID, 
            Guid storageID, 
            string name,
            string[] flags,
            HttpPostedFileBase file)
        {
            try
            {
                var m = Svc.ProcessOperation("CreateFile", new
                {
                    OwnerID = ownerID,
                    FolderID = folderID,
                    StorageID = storageID,
                    Name = name,
                    MimeType = file.ContentType,
                    Size = file.ContentLength,
                    Flags = flags.Merge(",")
                }, new
                {
                    DisclosureLevel = "Keys"
                });

                Guid fileGuid = JDM.Guid(m.Guid);
                using(var stream = file.InputStream)
                    Svc.UploadFile(fileGuid, stream);
                return RedirectToAction(Loc.Act("Edit").Set(new
                {
                    id = JDM.Int32(m.EntityID)
                }));
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Create"));
        }

        [HttpGet]
        public ActionResult Download(int id, 
            Guid tform, 
            IDictionary<String, String> tformProperties = null)
        {
            var m = Svc.ProcessOperation("GetFile", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Base"
            });
            if(m == null)
                return HttpNotFound();

            Guid fileGuid = JDM.Guid(m.Guid);
            string fileMimeType = JDM.String(m.MimeType);
            string dwlMimeType = String.Empty;
            string dwlName = JDM.String(m.Name);
            var fileStream = Svc.DownloadFile(fileGuid, 
                out dwlMimeType, 
                tform == Guid.Empty ? null : new List<TransformInfo>
                {
                    new TransformInfo
                    {
                        ID = tform,
                        Properties = tformProperties
                    }
                });

            if(!fileMimeType.Equals(dwlMimeType))
                dwlName = String.Format("{0}.{1}", dwlName, MimeTypeHelper.TypeToExt(dwlMimeType));

            return File(fileStream, dwlMimeType, dwlName);
        }

        [HttpGet, RestoreState]
        public ActionResult Edit(int id)
        {
            var m = Svc.ProcessOperation("GetFile", new
            {
                EntityID = id,
                Fetch = "Entire"
            }, new
            {
                DisclosureLevel = "Entire"
            });
            if(m == null)
                return HttpNotFound();
            return View(m);
        }

        [HttpPost, PersistState]
        public ActionResult Update(int id,
            int ownerID,
            int folderID,
            string name,
            string[] flags)
        {
            try
            {
                Svc.ProcessOperation("UpdateFile", new
                {
                    EntityID = id,
                    OwnerID = ownerID,
                    FolderID = folderID,
                    Name = name,
                    Flags = flags.Merge(",")
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id
            }));
        }

        [HttpGet, PersistState]
        public ActionResult Delete(int id)
        {
            try
            {
                Svc.ProcessOperation("DeleteFile", new
                {
                    EntityID = id
                });
                return RedirectToAction(Loc.Act("Index"));
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id
            }));
        }

        #endregion

        #region AJAX Actions

        [HttpPost]
        public ActionResult Grid(int? page,
            int? rows, 
            string sord, 
            string sidx,
            string searchTerm,
            string mimeType,
            int? ownerID,
            int? folderID,
            int? groupID,
            string createdFrom,
            string createdTo,
            string flagMask)
        {
            page = page.HasValue ? page.Value - 1 : 0;
            rows = rows.HasValue ? rows.Value : 30;
            sord = sord.Equals("desc") ? "Descending" : "Ascending";

            var m = Svc.ProcessOperation("SearchFiles", new 
            {
                Term = new
                {
                    Expression = searchTerm
                },
                MimeType = new
                {
                    Expression = mimeType
                },
                OwnerID = ownerID,
                FolderID = folderID,
                GroupID = groupID,
                FlagMask = flagMask,
                CreatedFrom = String.IsNullOrWhiteSpace(createdFrom) ? (DateTime?)null : Svc.DateTime(createdFrom),
                CreatedTo = String.IsNullOrWhiteSpace(createdTo) ? (DateTime?)null : Svc.DateTime(createdTo),
                Index = page * rows,
                Count = rows,
                SortBy = new[] 
                {
                    sidx
                },
                SortDir = sord
            }, new
            {
                DisclosureLevel = "Base"
            });
            var data = new List<Object>();

            foreach(var i in m.Items)
            {
                data.Add(new[] { 
                    JDM.Int32(i.EntityID),
                    JDM.String(i.Name),
                    JDM.String(i.MimeType),
                    Svc.DataSize((decimal)JDM.Int64(i.Size)),
                    Svc.DateTime((DateTime)JDM.DateTime(i.CreatedOn))
                });
            }

            return Json(new
            {
                pageIndex = page + 1,
                pageCount = Math.Ceiling(JDM.Double(m.TotalCount) / rows),
                totalCount = JDM.Int64(m.TotalCount),
                data = data.ToArray()
            });
        }

        [HttpPost]
        public ActionResult Storages()
        {
            dynamic m = Svc.ProcessOperation("ListFileStorages");
            var data = new List<Object>();

            foreach(var i in m)
            {
                data.Add(new
                {
                    id = JDM.Guid(i.ID),
                    value = JDM.String(i.Name)
                });
            }
            return Json(data.ToArray());
        }

        [HttpPost]
        public ActionResult Autocomplete(string term)
        {
            var m = Svc.ProcessOperation("GetFileDictionary", new
            {
                Term = new
                {
                    Expression = String.Format("{0}%", term)
                },
                Count = 10
            });
            var data = new List<Object>();

            foreach(var i in m.Items)
            {
                data.Add(new
                {
                    id = JDM.String(i.Key),
                    value = JDM.String(i.Value)
                });
            }
            return Json(data.ToArray());
        }

        #endregion
    }
}
